%{
	/* PARSER per un server HTML */
	#define MAXDEF //Definizione della dimensione massima di un vettore
	#define SIZE 150 //Definizione della dimensione del buffer
	
	//Librerie utilizzate
	#include <time.h>
	#include <stdio.h>
	#include <stdlib.h>
	#include <string.h>
	#include <malloc.h>
	#include "symboltable.h"

	int errore=0; //Variabile Booleana
	

	void yyerror(char *);
	int yylex(void);
	
	char *comando=(char *)0;
	char *ind=(char *)0;
	char *vers=(char *)0;
	stringlist *connection = (stringlist *)0;
	stringlist *useragent = (stringlist *)0;
	stringlist *host = (stringlist *)0;
	stringlist *acceptencoding = (stringlist *)0;
	stringlist *acceptlist=(stringlist *)0;
	
	void data(){
		char buffer[SIZE];
  		time_t curtime;
  		struct tm *loctime;

  		/* Get the current */
  		curtime = time (NULL);

  		/* Convert it to local time representation.  */
  		loctime = localtime (&curtime);

  		/* Scrivo la data come richiesta nel testo dell'esercizio  */
  		strftime (buffer, SIZE, "%a, %d %b %Y %H:%M:%S %Z\n", loctime);
  		fputs (buffer, stdout);
	
	}
	
	install ( char *insertstring, stringlist *listadaassociare){//Installa l'istanziazione all'interno della symbol table 
		stringlist *s;
		s = putsym (insertstring,listadaassociare);
		printf(s->stringa);
	}

%}

%union{
	char *com;
	char *indirizzo;
	char *versione;
	char *headerstring;
}

%token <headerstring> CONNECTION
%token <headerstring> USERAGENT
%token <headerstring> ACCEPT
%token <headerstring> ACCEPTENCODING
%token <com> COMANDO
%token <headerstring> HOST
%token <versione> VERSIONE
%token <indirizzo> INDIRIZZO

%type <headerstring> header




%%

richiesta:
	COMANDO INDIRIZZO VERSIONE headers	{ 
											comando = (char *) malloc (strlen($1)+1);
											strcpy(comando,$1);
											
											ind = (char *) malloc (strlen($2)+1);
											strcpy(ind,$2);
											
											vers = (char *) malloc (strlen($3)+1);
											strncpy(vers,$3,8);
																	
										
										}
	;

headers:
    headers header
	|	
	;

header:
	CONNECTION			{
							stringlist *s;
							s = putsym($1,&connection);
						}
	| ACCEPT			{ 
							stringlist *s;
							char *temp;
							temp = strtok ($1,",");
  							while (temp != NULL)
  							{
    							s = putsym(temp,&acceptlist);
    							temp = strtok (NULL, " ,");
  							}
						}
	| USERAGENT			{ 
							stringlist *s;
							s = putsym($1,&useragent); 
						}
	| ACCEPTENCODING	{ 
							stringlist *s;
							char *temp;
							temp = strtok ($1,",");
  							while (temp != NULL)
  							{
    							s = putsym(temp,&acceptencoding);
    							temp = strtok (NULL, " ,");
  							}
						}
	| HOST 				{ 
							stringlist *s;
							s = putsym($1,&host); 
						}
	;

%%

void yyerror(char *s) {
	printf("Errore nel parsing della richiesta, controlla di non aver messo più di un comando\n\n");
	errore=2;//Errore nel parsing
	FILE *fp;
	fp=fopen("request.log", "w+");
	fprintf(fp,"HTTP BAD REQUEST\n");
	fclose(fp);
}

int main(void) {
	stringlist *tempacceptlist;
	yyparse();
	
	/*
			
			STAMPA DEL FILE request.log
	
	*/
	
	if(errore!=2){
		FILE *fp;
		fp=fopen("request.log", "w+");

		if(comando!=0){
			fprintf(fp,comando);
			fprintf(fp," ");
		}
		if(ind!=0){
			fprintf(fp,ind);
			fprintf(fp," ");
		}
		if(vers!=0)
			fprintf(fp,vers);
		else
			fprintf(fp,"\n");
		
		if(numberOfElm(connection)>0){
			fprintf(fp, "\n");
			fstampastringaTag(fp,"Connection: ", connection);
		}
		if(numberOfElm(useragent)>0){
			fprintf(fp, "\n");
			fstampastringaTag(fp, "User-Agent: ",useragent);
		}
		eliminadoppie(acceptlist);
		if(numberOfElm(acceptlist)>0){
			fprintf(fp,"\nAccept: ");
			fstampastringa(fp,acceptlist);
		}
		if(numberOfElm(acceptencoding)>0){
			fprintf(fp,"\nAccept-Encoding: ");
			fstampastringa(fp,acceptencoding);
		}
		
		if(numberOfElm(acceptencoding)>0){
			fprintf(fp,"\n");
			fstampastringaTag(fp, "Host: ", host);
		}
		
	
		fclose(fp);//Chiusura del file
	}
	/*
	
		FINE SCRITTURA FILE ---- INIZIO PRINT RISPOSTA
	
	*/
	if(numberOfElm(useragent)>1)//Se c'è più di un header User-Agent
		errore=1;	
		
	//Controlli su HOST in base alla versione dell'HTTP	
	if(strcmp(vers,"HTTP/1.1")==0 && numberOfElm(host)!=1){
		errore=1;
	}
	if((strcmp(vers,"HTTP/1.0")==0 || strcmp(vers,"HTTP/0.9")==0) && numberOfElm(host)>1){
		errore=1;
	}
	if(numberOfElm(acceptlist)==0)//Se non c'è almeno un header accept
		errore=1;	
	
	
	if(errore!=0){//Stampa la Bad Request	
		printf("\n\n%s%s",vers," 400 Bad Request\n");
		printf("Date: ");
		data();//Stampa la data nel formato richiesto
		printf("Server: Apache/1.3.29 (Unix) PHP/4.3.4\n");
		printf("Content-Type: text/html; charset=iso-8859-1\n\n\n");  
    return 1; //errore
	} else {
		printf("\n\n%s%s",vers," 200 OK\n");
		printf("Date: ");
		data();//Stampa la data nel formato richiesto
		printf("Server: Apache/1.3.29 (Unix) PHP/4.3.4\n");
		printf("Content-Type: ");
		printf(acceptlist->stringa);
		printf("; charset=utf-8\n\n\n");
    return 0;  //tutto ok
	}
  return 1; // qui non ci dovremmo arrivare mai
}
